#!usr/bin/env python3
# -*- conding: utf-8 -*-

# 第四章 迭代器和生成器

def gener(n): #生成器
    while(n>0):
        yield n
        n-=1
    print("Done!") #该行输出 只有访问完生成器所有元素才会执行

myg = gener(6)
print(myg)
for n in myg:
    pass
    #print(n)

print(list(reversed([1,2,3]))) # reversed 返回的是一个反转迭代器 不是一个list

# 可以在自定义类中实现 __reversed__ 函数实现反向迭代

class Node(object):
    def __init__(self,start):
        self.start = start
    
    def __iter__(self):
        n = self.start
        while(n>0):
            yield n
            n-=1
    def __reversed__(self): # 实现 __reversed__ 方法就可以生成一个反向生成器
        n = 1
        while(n<=self.start):
            yield n
            n+=1


for n in Node(5):
    print('从大到小',n)
print("-----------------------")
for n in reversed(Node(5)):
    print('从小到大',n)

n = Node(10) # n 是一个迭代器 同时也是一个实例

print(n.start)

# 2017年6月7日22:17:12 P123

#迭代器实现切片操作

import itertools  

def countN():
    n = 1
    while True:
        yield n
        n+=1

c = countN()

c1 = itertools.islice(c,0,20) # 通过 itertools.islice 对迭代器进行切片 依然返回一个迭代器 并且消耗掉原迭代器的数据
print(list(c1)) # 通过输出发现 同时会截取下标0和20的值

# 解决排列组合问题

from itertools import permutations,combinations


ary = [1,1,3,4]

# 返回的是 一个集合ary中的所有可能的排列 (注意 因为ary中有重复的元素，所有这个函数返回的是也是有相同的组合)
aryG = permutations(ary)  #返回的是一个 itertools.permutations 实例 其实也是一个迭代器每个元素是一个元组 tuple
myList = list(aryG)
print(type(aryG),len(myList))

aryG = permutations(ary,2) # 也可以指定每个组合的长度，也就是元组的个数

comb = combinations(ary,2) # 得到组合 这里表示获取ary中任意两个元素的所有组合
print(list(comb))

# 迭代集合的键和值

myList = [3,4]
start = 1 # 定义开始下标
for k,v in enumerate(myList,start):
    print(k,v)

# zip 和 zip_longest
from itertools import zip_longest

#zip 函数迭代遇到某个迭代器结尾则结束
#zip_longest 函数会迭代所有迭代器 其他已经结束的会用None代替
aryA = [1,2,3]
aryB = ['a','b','c','d','e']
print("---------zip-----------")
for x,y in zip(aryA,aryB):
    print(x,y)

print("---------zip_longest--------")
for x,y in zip_longest(aryA,aryB):
    print(x,y)

d1 = dict(zip(aryB,aryA)) # 可以通过数据快速创建一个k-v 字典
print(d1)

# 一次迭代多个序列

from itertools  import chain

for x in chain([1,2],['a','b']): # 把输入的多个序列 依次迭代出来
    print(x)


